<?php
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . 'wsr.inc.php';
require_once MORIARTY_DIR . "simplegraph.class.php";

require_once WSR_DIR . "multiiterator.class.php";
require_once WSR_DIR . "wrappediterator.class.php";
require_once WSR_DIR . "mapiterator.class.php";

class AxGraph extends SimpleGraph {
	
  function __construct($graph=false){
	if($graph && is_object($graph) && is_a($graph,'SimpleGraph') ){
      $this->_index = $graph->_index;
      $this->_ns = $graph->_ns;
    } else {
      parent::__construct($graph);
    }
  }

/*
  // already there!
  function get_subject_properties($s) {
    return keys($this->_index[$s]);
  }
*/

  function filter($callback) {
    $graph = new AxGraph();
    $tuples = $this->to_iterator($callback);
	$graph->from_iterator($tuples);
    return $graph;
  }
  
  
  function make_resource_graph() {  // N.B. only contains resource links
    return $this->filter(array($this,'_make_resource_graph_callback'));
  }
  
  function _make_resource_graph_callback($s,$p,$obj) {
	//echo "_make_resource_graph_callback( $s, $p, ";
	//print_r($obj);
	//echo " )\n";
    return $obj['type'] != 'literal';
  }
  
  function make_inverse_graph() {  // N.B. only contains resource links
    $graph = new AxGraph();
    $tuples = $this->to_resource_iterator();
	$inverse_tuples = iterator_map( $tuples, array($this,'_make_inverse_graph_callback') );
	$graph->from_resource_iterator($inverse_tuples);
    return $graph;
  }
  
  function _make_inverse_graph_callback($tuple) {
    return array($tuple[2],$tuple[1],$tuple[0]);
  }
  
  
  function to_resource_iterator($filter=false) {
    return new AxGraphResourceIterator($this,$filter);
  }

  function to_iterator($filter=false) {
    return new AxGraphIterator($this,$filter);
  }

  function from_iterator($tuples) {
    foreach ( $tuples as $tuple ) {
	  $s = $tuple[0];
	  $p = $tuple[1];
	  $obj = $tuple[2];
	  $type = $obj['type'];
	  $o = $obj['value'];
	  //echo "from_iterator($s,$p,$o,$type)\n";
	  if ( $obj['type'] == 'literal' ) {
        $this->add_literal_triple($s,$p,$o,$obj['lang'],$obj['datatype']);
	  } else {
        $this->add_resource_triple($s,$p,$o);
	  }
    }
  }

  function from_resource_iterator($tuples) {
    foreach ( $tuples as $tuple ) {
	  $s = $tuple[0];
	  $p = $tuple[1];
	  $o = $tuple[2];
      $this->add_resource_triple($s,$p,$o);
    }
  }

}

class AxGraphIterator extends WrappedIterator implements Iterator {
  var $graph;
  var $iterator;
  var $filter;
  function __construct($graph,$filter=false){
    //echo "axgi:__construct(arr,$depth,".($filter ? $filter[1] : 'NONE' ).")\n";
    $this->graph = $graph;
    $this->filter = $filter;
	if ( $filter ) {
	  $myfilter = array($this,'_filter');
	} else {
	  $myfilter = false;
	}
	$this->iterator = new MuItiIterator($graph->get_index(),3,$myfilter);
    //echo "after axgi:__construct():".($this->iterator->filter ? $this->iterator->filter[1] : 'NONE' )."\n";
  }
  
  function _filter($pos,$val,$keys) {
    if ( ! $this->filter ) {
	  $res = true;
	} else {
	  $res = call_user_func( $this->filter, $keys[0], $keys[1], $val );
	}
	//echo "AxGraphIterator:_filter($pos,".$val['value'].":".$keys[0].":".$keys[1].")\n=>$res\n\n";
	return $res;
  }
  
  function current() {
	//echo "axgi:current()\n";
	$val = $this->iterator->current();
	$keys = $this->iterator->keys();
    return array( $keys[0], $keys[1], $val ); 
  }
}

class AxGraphResourceIterator extends AxGraphIterator implements Iterator {

  var $resource_triple_filter;
  function __construct($graph,$filter=false){
    parent::__construct($graph,array($this,'_resource_filter'));
    $this->resource_triple_filter = $filter;
  }
  function current() {
	$triple = parent::current();
	//echo "axgi:current()\n";
	$val = $this->iterator->current();
	$keys = $this->iterator->keys();
    return array( $triple[0], $triple[1], $triple[2]['value'] ); 
  }

  function _resource_filter($s,$p,$o_obj) {
	if ( $o_obj['type'] == 'literal' ) {
	  $res = false;
	} else if ( ! $this->resource_triple_filter ) {
	  $res = true;
	} else {
	  $res = call_user_func( $this->resource_triple_filter, $s,$p,$o_obj['value'] );
	}
	//echo "_resource_filter($s,$p,".$o_obj['type'].":".$o_obj['value'].")\n=>$res\n\n";
	return $res;
  }

}



?>